package com.jcfk.system.service;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.jcfk.common.cache.redis.service.RedisStringService;
import com.jcfk.common.core.exception.CustomException;
import com.jcfk.system.dao.SysUserDao;
import com.jcfk.system.domain.wechat.WeChatCreateRequest;
import com.jcfk.system.domain.wechat.WeChatResponse;
import com.jcfk.system.domain.wechat.create.WeChatAppChatCreateRequest;
import com.jcfk.system.domain.wechat.create.WeChatAppChatCreateResponse;
import com.jcfk.system.domain.wechat.send.WeChatSendRequest;
import com.jcfk.system.domain.wechat.send.WeChatSendSecretRequest;
import com.jcfk.system.domain.wechat.send.WeChatSendTextCard;
import com.jcfk.system.domain.wechat.token.WeChatGetTokenRequest;
import com.jcfk.system.domain.wechat.token.WeChatGetTokenResponse;
import com.jcfk.system.domain.wechat.token.WeChatTokenRequest;
import com.jcfk.system.domain.wechat.user.*;
import com.jcfk.system.enums.MessageTypeEnum;
import com.jcfk.system.utils.CipherUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static cn.hutool.core.util.CharsetUtil.UTF_8;

@Component("sendWeChatMessageService")
public class SendWeChatMessageService {
    private static final String TOKEN_REDIS_KEY_PREFIX = "wx_access_token";
    @Value("${wx-cp-config.createUrl}")
    private String createUrl;
    @Value("${wx-cp-config.sendUrl}")
    private String sendUrl;
    @Value("${wx-cp-config.userIdUrl}")
    private String getUserId;
    @Value("${wx-cp-config.secret}")
    private String secret;
    @Value("${wx-cp-config.tokenUrl}")
    private String tokenUrl;
    @Value("${system.secret}")
    private String sysSecret;
    @Value("${wx-cp-config.userInfoUrl}")
    private String getUserInfoUrl;
    @Value("${wx-cp-config.userDetail}")
    private String getUserDetailUrl;
    @Value("${wx-cp-config.corpid}")
    private String corPid;
    @Value("${wx-cp-config.agentid}")
    private String agentId;
    @Value("${wx-cp-config.authorize}")
    private String authorizeUrl;
    @Autowired
    private RedisStringService redisStringService;
    @Autowired
    SysUserDao sysUserDao;

    /**
     * 创建微信群聊
     *
     * @param weChatCreateRequest
     */
    public void creatWxChatTeam(WeChatCreateRequest weChatCreateRequest) {
        String accessToken = getWXAccessToken();
        WeChatGetUserIdRequest ownerUserIdRequest = new WeChatGetUserIdRequest();
        ownerUserIdRequest.setMobile(weChatCreateRequest.getOwnerMobile());
        String ownerUserId = getUserId(accessToken, weChatCreateRequest.getOwnerMobile());
        if (Objects.isNull(ownerUserId)) {
            throw new CustomException("群管理手机号异常");
        }
        List<String> userIdList = new ArrayList<>();
        userIdList.add(ownerUserId);
        for (String userMobile : weChatCreateRequest.getUserMobiles()) {
            String userId = getUserId(accessToken, userMobile);
            if (Objects.nonNull(userId)) {
                userIdList.add(userId);
            }
        }
        if (userIdList.size() < 2) {
            throw new CustomException("有效成员手机号不足");
        }
        WeChatAppChatCreateRequest weChatAppchatCreateRequest = new WeChatAppChatCreateRequest();
        weChatAppchatCreateRequest.setChatid(weChatCreateRequest.getChatId());
        weChatAppchatCreateRequest.setName(weChatCreateRequest.getName());
        weChatAppchatCreateRequest.setOwner(ownerUserId);
        weChatAppchatCreateRequest.setUserlist(userIdList);
        appChatCreate(accessToken, weChatAppchatCreateRequest);
    }

    /**
     * 发送微信群聊消息
     *
     * @param weChatSendRequest
     */
    public void sendWeChat(WeChatSendRequest weChatSendRequest) {
//        String accessToken = "-XFZV8wiKynuNjR9LxW5zBh2p899pK2ATajcr93i0rJIk_X4_mAH9DDAupIjRBwWVVxIuRIF128__pAjsM67rPUiVIQduEJ3CJjY11wJNH36-NfHarjiXmRtqy2jnOqMBUtoxtjh72Owo-Cl9_tHd8_8ZbeYDrdI07ApHLmNCFdRgSnt-9CNUUKJUjE5BbPQO5HXGGz09iDiWc5xoU0AOw";
        String accessToken = getWXAccessToken();
        appChatSend(accessToken, weChatSendRequest);
    }

    /**
     * 获取企业微信用户id
     *
     * @param accessToken
     * @param weChatGetUserIdRequest
     * @return
     */
    public String getUserId(WeChatTokenRequest accessToken, WeChatGetUserIdRequest weChatGetUserIdRequest) {
        RestTemplate restTemplate = new RestTemplate();
        WeChatGetUserIdResponse response = restTemplate.postForObject(getUserId, weChatGetUserIdRequest, WeChatGetUserIdResponse.class, accessToken);
        return checkResponse(response).getUserid();
    }

    public String getUserId(String accessToken, String mobile) {

        RestTemplate restTemplate = new RestTemplate();

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("mobile", mobile);

        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, (MultiValueMap<String, String>) headers);

        Map<String, Object> response = restTemplate.postForObject(getUserId + "?access_token=" + accessToken, requestEntity, Map.class);

        if (response != null && response.containsKey("userid")) {
            return (String) response.get("userid");
        } else {
            return "";
        }
    }


    /**
     * 根据微信code获取企业微信用户
     *
     * @param accessToken
     * @param code
     * @return
     */
    public WeChatGetUserInfoResponse getUserInfo(String accessToken, String code) {
        RestTemplate restTemplate = new RestTemplate();
        WeChatGetUserInfoResponse response = restTemplate.getForObject(getUserInfoUrl + "?access_token=" + accessToken + "&code=" + code, WeChatGetUserInfoResponse.class);
        return checkResponse(response);
    }

    /**
     * 根据成员票据获取企业微信用户详情
     *
     * @param accessToken
     * @param weChatGetUserDetailRequest
     * @return
     */
    public WeChatGetUserDetailResponse getUserDetail(WeChatTokenRequest accessToken, WeChatGetUserDetailRequest weChatGetUserDetailRequest) {
        RestTemplate restTemplate = new RestTemplate();
        WeChatGetUserDetailResponse response = restTemplate.postForObject(getUserDetailUrl, weChatGetUserDetailRequest, WeChatGetUserDetailResponse.class, accessToken);
        return checkResponse(response);
    }

    /**
     * 创建微信群聊
     *
     * @param accessToken
     * @param weChatAppchatCreateRequest
     * @return
     */
    public String appChatCreate(String accessToken, WeChatAppChatCreateRequest weChatAppchatCreateRequest) {
        RestTemplate restTemplate = new RestTemplate();
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("chatid", weChatAppchatCreateRequest.getChatid());
        requestBody.put("owner", weChatAppchatCreateRequest.getOwner());
        requestBody.put("name", weChatAppchatCreateRequest.getName());
        requestBody.put("userlist", weChatAppchatCreateRequest.getUserlist());

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, (MultiValueMap<String, String>) headers);

        Map<String, Object> response = restTemplate.postForObject(createUrl + "?access_token=" + accessToken, requestEntity, Map.class);

        if (response != null && response.containsKey("errcode") && response.get("errcode").equals(0)) {
            return weChatAppchatCreateRequest.getChatid();
        } else {
            return "";
        }
    }

    /**
     * 发送微信群聊消息
     *
     * @param accessToken
     * @param weChatSendRequest
     */
    public void appChatSend(String accessToken, WeChatSendRequest weChatSendRequest) {
        RestTemplate restTemplate = new RestTemplate();
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("chatid", weChatSendRequest.getChatid());
        requestBody.put("safe", weChatSendRequest.getSafe());
        requestBody.put("msgtype", weChatSendRequest.getMsgtype());
        weChatSendRequest.getTextcard().setBtntxt("更多");
        requestBody.put("text", weChatSendRequest.getText());
        requestBody.put("textcard", weChatSendRequest.getTextcard());
        requestBody.put("markdown", weChatSendRequest.getMarkdown());
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, (MultiValueMap<String, String>) headers);

        Map<String, Object> response = restTemplate.postForObject(sendUrl + "?access_token=" + accessToken, requestEntity, Map.class);
        if (response != null && response.containsKey("errcode") && response.get("errcode").equals(0)) {

        } else {
            throw new CustomException("消息发送失败");
        }

    }

    private <T extends WeChatResponse> T checkResponse(T response) {
        if (response != null) {
            if (0 == response.getErrcode()) {
                return response;
            }
            throw new CustomException(response.getErrmsg());
        }
        throw new CustomException(response.getErrmsg());
    }

    /**
     * 处理自动登录跳转请求
     *
     * @param weChatSendSecretRequest
     * @return
     */
    public WeChatSendRequest dealSecretUrl(WeChatSendSecretRequest weChatSendSecretRequest) throws UnsupportedEncodingException {
        WeChatSendRequest weChatSendRequest = weChatSendSecretRequest.getWeChatSendRequest();
        if (MessageTypeEnum.TEXT_CARD.getValue().equals(weChatSendRequest.getMsgtype())) {
            WeChatSendTextCard textCard = weChatSendRequest.getTextcard();
            String url = textCard.getUrl();
            LocalDateTime localDateTime = LocalDateTime.now();
            long epochMillis = localDateTime.atZone(ZoneOffset.UTC).toInstant().toEpochMilli();
            String params = String.format("%s_%s", weChatSendSecretRequest.getEmpNo(), epochMillis);
            String decryptParam = CipherUtils.encrypt(params, sysSecret);
            String encoderParam = URLEncoder.encode(decryptParam, "UTF-8");
            textCard.setUrl(String.format(url + "?loginSecret=%s&topage=%s", encoderParam, weChatSendSecretRequest.getToPage()));
        }
        return weChatSendRequest;
    }

    /**
     * 处理权限登录跳转请求
     *
     * @param weChatSendRequest
     * @return
     */
    public WeChatSendRequest dealAuthSecretUrl(WeChatSendRequest weChatSendRequest) throws UnsupportedEncodingException {
        if (MessageTypeEnum.TEXT_CARD.getValue().equals(weChatSendRequest.getMsgtype())) {
            WeChatSendTextCard textCard = weChatSendRequest.getTextcard();
            String url = textCard.getUrl();
            String redirectUri = URLEncoder.encode(url, UTF_8);
            String appid = corPid;
            LocalDateTime localDateTime = LocalDateTime.now();
            long state = localDateTime.atZone(ZoneOffset.UTC).toInstant().toEpochMilli();
            String authUrl = String.format(authorizeUrl, appid, redirectUri, state, agentId);
            textCard.setUrl(authUrl);
        }
        return weChatSendRequest;
    }

    /**
     * 通过企业微信用户code获取系统empNo
     *
     * @param code
     * @param state
     * @return
     */
    public String getEmpNoByWeChat(String code, String state) {
        String accessToken = getWXAccessToken();
        WeChatGetUserInfoResponse weChatGetUserInfoResponse = getUserInfo(accessToken, code);
        if (weChatGetUserInfoResponse != null) {
            String userTicket = weChatGetUserInfoResponse.getUser_ticket();
            WeChatGetUserDetailResponse weChatGetUserDetailResponse = getUserDetail(new WeChatTokenRequest(accessToken), new WeChatGetUserDetailRequest(userTicket));
            if (weChatGetUserDetailResponse != null) {
                String mobile = weChatGetUserDetailResponse.getMobile();
                return sysUserDao.getEmpNoByMobile(mobile);
            }
        }
        return null;
    }

    /**
     * 根据微信code获取企业微信用户
     *
     * @param weChatGetTokenRequest
     * @return
     */
    public WeChatGetTokenResponse getToken(WeChatGetTokenRequest weChatGetTokenRequest) {
        RestTemplate restTemplate = new RestTemplate();
        WeChatGetTokenResponse response = restTemplate.getForObject(tokenUrl, WeChatGetTokenResponse.class, weChatGetTokenRequest);
        if (response != null && 0 == response.getErrcode()) {
            return response;
        }
        return null;
    }

    /**
     * 获取企业微信的accessToken
     */
    public String getWXAccessToken() {
        // 从Redis中获取access_token
        String accessResult = redisStringService.getValue("wx_access_token" + corPid);
        if (accessResult != null) {
            return accessResult;
        }
        // 构建请求参数
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("corpid", corPid);
        paramMap.put("corpsecret", secret);

        // 发送GET请求获取access_token
        String response = HttpUtil.get(tokenUrl, paramMap);
        cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(response);

        // 检查请求结果是否成功
        if (jsonObject.getInt("errcode") != 0) {
            throw new RuntimeException("获取企业微信access_token失败：" + jsonObject.getStr("errmsg"));
        }

        // 缓存wx_access_token到redis
        redisStringService.setValue("wx_access_token" + corPid, jsonObject.getStr("access_token"), jsonObject.getLong("expires_in"), TimeUnit.SECONDS);

        return jsonObject.getStr("access_token");
    }


}
